package com.shenzhenai.jetpackcomposegesture


import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.core.TweenSpec
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.AnchoredDraggableState
import androidx.compose.foundation.gestures.DraggableAnchors
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.anchoredDraggable
import androidx.compose.foundation.gestures.animateTo
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.gestures.rememberScrollableState
import androidx.compose.foundation.gestures.rememberTransformableState
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.gestures.transformable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.*
import com.shenzhenai.jetpackcomposegesture.ui.theme.DN_Compose_LearnTheme
import kotlin.math.roundToInt

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            DN_Compose_LearnTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    GestureSample(modifier = Modifier.padding(innerPadding))
                }
            }
        }
    }

    @Composable
    fun GestureSample(modifier: Modifier = Modifier) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center,
            modifier = modifier.fillMaxSize()
        ) {
//            ClickableSample()
//            ScrollBoxes()
//            ScrollBoxesSmooth()
//            ScrollableSample()
//            NestedScrollSample()

//            DraggableSample()
//            DragWhereYouWantSample()

//            SwipeableSample()
            TransformableSample()
        }
    }

    /**
     * 可点击案例
     */
    @Composable
    fun ClickableSample() {
        val count = remember {
            mutableStateOf(0)
        }

        Text(
            text = count.value.toString(),
            textAlign = TextAlign.Center,
            modifier = Modifier
                //  实现点击
//                .clickable {
//                    count.value += 1
//                }
                // 使用更底层的api，实现点击
                .pointerInput(Unit) {
                    detectTapGestures(
                        onTap = {
                            Log.e("young_test", "onTap")
                        },
                        onDoubleTap = {
                            Log.e("young_test", "onDoubleTap")
                        },
                        onLongPress = {
                            Log.e("young_test", "onLongPress")
                        },
                        onPress = {
                            Log.e("young_test", "onPress")
                        }
                    )
                }
                .wrapContentSize()
                .background(Color.LightGray)
                .padding(horizontal = 50.dp, vertical = 40.dp)
        )
    }


    /**
     * 滚动修饰符
     */
    @Composable
    fun ScrollBoxes() {
        Column(
            modifier = Modifier
                .background(Color.LightGray)
                .size(100.dp)
                // 设置垂直滚动，类似  LinearLayout 被 ScrollView
                .verticalScroll(rememberScrollState())
        ) {
            repeat(10) {
                Text(text = "Item ${it}", modifier = Modifier.padding(2.dp))
            }
        }
    }

    // 借助ScrollState，您可以更改滚动位置或获取当前状态。
    @Composable
    fun ScrollBoxesSmooth() {
        val state = rememberScrollState()

        LaunchedEffect(key1 = Unit) {
            state.animateScrollTo(100)
        }

        Column(
            modifier = Modifier
                .background(Color.LightGray)
                .size(100.dp)
                // 设置垂直滚动，类似  LinearLayout 被 ScrollView
                .verticalScroll(state = state)
        ) {
            repeat(10) {
                Text(text = "Item ${it}", modifier = Modifier.padding(2.dp))
            }
        }
    }


    //  可滚动的修饰符
    // scrollable修饰符与滚动修饰符不同，区别在于scrollable可检测滚动手势，但不会偏移其内容。
    @Composable
    fun ScrollableSample() {
        var offset by remember {
            mutableStateOf(0f)
        }

        Box(
            modifier = Modifier
                .size(150.dp)
                .scrollable(
                    orientation = Orientation.Vertical,
                    state = rememberScrollableState { delta ->
                        offset += delta
                        delta
                    }
                )
                .background(Color.LightGray),
            contentAlignment = Alignment.Center
        ) {
            Text(text = offset.toString())
        }
    }

    // 嵌套滚动
    @Composable
    fun NestedScrollSample() {

        val gradient = Brush.verticalGradient(
            0f to Color.Gray,
            1000f to Color.White
        )

        Box(
            modifier = Modifier
                .background(Color.LightGray)
                .verticalScroll(rememberScrollState())
                .padding(32.dp),
        ) {
            Column {
                repeat(6) {
                    Box(
                        modifier = Modifier
                            .height(128.dp)
                            .verticalScroll(rememberScrollState())
                    ) {
                        Text(
                            text = "Item ${it}",
                            modifier = Modifier
                                .border(12.dp, Color.DarkGray)
                                .background(brush = gradient)
                                .padding(24.dp)
                                .height(150.dp) // Text 高度大于外部容器Box的高度
                        )
                    }
                }
            }
        }
    }

    /**
     * 拖动
     */
    @Composable
    fun DraggableSample() {

        var offsetX by remember {
            mutableStateOf(0f)
        }

        Text(
            text = "Drag me!",
            modifier = Modifier
                .offset {
                    IntOffset(offsetX.roundToInt(), 0)
                }
                .draggable(
                    orientation = Orientation.Horizontal,
                    state = rememberDraggableState { delta ->
                        // 监听拖拽的偏移量
                        offsetX += delta
                    })
        )
    }

    // 如果您需要控制整个拖动手势，请考虑改为通过pointerinput修饰符使用拖动手势检测器。
    @Composable
    fun DragWhereYouWantSample() {
        Box(modifier = Modifier.fillMaxSize()) {
            var offsetX by remember {
                mutableStateOf(0f)
            }
            var offsetY by remember {
                mutableStateOf(0f)
            }
            Box(
                modifier = Modifier
                    .offset {
                        IntOffset(offsetX.roundToInt(), offsetY.roundToInt())
                    }
                    .background(Color.Blue)
                    .size(50.dp)
                    .pointerInput(Unit) {
                        detectDragGestures { change, dragAmount ->
                            offsetX += dragAmount.x
                            offsetY += dragAmount.y
                        }
                    }
            ) {

            }
        }
    }


    enum class DragValue { Start, Center, End }

    /**
     * 滑动
     */
    @OptIn(ExperimentalFoundationApi::class)
    @SuppressLint("RememberReturnType")
    @Composable
    fun SwipeableSample() {
        val width = 96.dp
        val squareSize = 48.dp

        /**
         *
         * 从 Swipeable 迁移到 AnchoredDraggable
         * https://developer.android.google.cn/develop/ui/compose/touch-input/pointer-input/migrate-swipeable?hl=zh-cn
         *
         *
         *  val anchors = DraggableAnchors {
         *         Start at -100.dp.toPx()
         *         Center at 0f
         *         End at 100.dp.toPx()
         *     }
         *     val state = remember {
         *         AnchoredDraggableState(anchors = anchors)
         *     }
         *     Box(
         *         Modifier.offset { IntOffset(x = state.requireOffset(), y = 0) }
         *     )
         */

//        val density = LocalDensity.current
//
//        val start = with(LocalDensity.current) { 0.dp.toPx() }
//        val center = 0f
//        val end = with(LocalDensity.current) { 100.dp.toPx() }
//
//
//        // dp 转px，需要使用   with(LocalDensity.current) 这种写法
////        with(LocalDensity.current) {
////            start = 0.dp.toPx()
////            end = 100.dp.toPx()
////        }
//
//
//        val anchors = DraggableAnchors {
//            DragValue.Start at start
//            DragValue.Center at center
//            DragValue.End at end
//        }
//        val state = remember {
//            AnchoredDraggableState(anchors = anchors,
//                initialValue = DragValue.Start,
//                positionalThreshold = { distance ->
//                    // 位置阈值
//                    distance * 0.5f
//                },
//                animationSpec = tween(durationMillis = 1000),
//                velocityThreshold = {
//                    // 速度阈值
//                    with(density) { 125.dp.toPx() }
//                },
//                confirmValueChange = {
//                    true
//                })
//        }
//
//
//        SideEffect {
//            state.updateAnchors(DraggableAnchors {
//                DragValue.Start at end
//                DragValue.Center at center
//                DragValue.End at end
//            })
//        }
//
//
//        Box(
//            modifier = Modifier
//                .width(width)
//                .background(Color.LightGray)
//
//        ) {
//            Box(
//                modifier = Modifier
//                    .offset {
//                        IntOffset(
//                            state
//                                .requireOffset()
//                                .toInt(), 0
//                        )
//                    }
//                    .size(squareSize)
//                    .background(Color.DarkGray)
//            )
//        }


        SwitchDemo()
    }

    /**
     * deepSeek 提供的实现自定义的switch的代码
     */
    @Composable
    fun SwitchDemo() {
        var isSwitchChecked by remember { mutableStateOf(false) }

        Column(
            modifier = Modifier.padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            Text(text = if (isSwitchChecked) "开关已打开" else "开关已关闭")
            Spacer(modifier = Modifier.height(16.dp))
            // 使用自定义的 DraggableSwitch
            DraggableSwitch(
                isChecked = isSwitchChecked,
                onCheckedChange = { newState -> isSwitchChecked = newState }
            )
        }
    }


    // 重要：AnchoredDraggable 相关API可能尚处于实验阶段，使用时请注意
    @OptIn(ExperimentalFoundationApi::class)
    @Composable
    fun DraggableSwitch(
        isChecked: Boolean,
        onCheckedChange: (Boolean) -> Unit,
        modifier: Modifier = Modifier,
        width: Dp = 52.dp,
        height: Dp = 28.dp,
        thumbSize: Dp = 20.dp,
        checkedColor: Color = MaterialTheme.colorScheme.primary,
        uncheckedColor: Color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f)
    ) {
        // 1. 定义锚点位置（开和关）
        val dragWidth = with(LocalDensity.current) { (width - thumbSize).toPx() } // 可拖动的总长度

        // 2. 创建 AnchoredDraggableState
        val draggableState = remember(isChecked) {
            AnchoredDraggableState(
                initialValue = isChecked,
                positionalThreshold = { totalDistance: Float -> totalDistance * 0.5f }, // 拖动超过50%则切换状态
                velocityThreshold = { dragWidth }, // 速度阈值
                animationSpec = TweenSpec(durationMillis = 300), // 动画配置
            ).apply {
                // 更新锚点配置
                updateAnchors(
                    DraggableAnchors {
                        false at 0f   // "关"状态对应位置0
                        true at dragWidth // "开"状态对应位置 dragWidth
                    }
                )
            }
        }

        // 3. 使用 AnchoredDraggable 修饰符
        Box(
            modifier = modifier
                .size(width = width, height = height)
                .clip(RoundedCornerShape(percent = 50)) // 切成圆形，形成常见的开关外观
                .background(color = if (isChecked) checkedColor else uncheckedColor)
                .anchoredDraggable(
                    state = draggableState,
                    orientation = Orientation.Horizontal,
                    enabled = true // 可根据需要启用或禁用拖动
                ),
            contentAlignment = if (isChecked) Alignment.CenterEnd else Alignment.CenterStart
        ) {
            // 4. 绘制可拖动的拇指（Thumb）
            Box(
                modifier = Modifier
                    .size(thumbSize)
                    .clip(CircleShape)
                    .background(MaterialTheme.colorScheme.surface)
                    .offset(x = draggableState.offset.dp) // 拇指位置与 draggableState 的偏移量绑定
            )
        }

        // 5. 状态同步（可选但重要）
        // 当 draggableState 的目标值(currentValue)发生变化时，通知外部
        LaunchedEffect(draggableState.currentValue) {
            if (draggableState.currentValue != isChecked) {
                onCheckedChange(draggableState.currentValue)
            }
        }
        // 当外部的 isChecked 变化时，动画地更新到对应状态
        LaunchedEffect(isChecked) {
            if (isChecked != draggableState.currentValue) {
                draggableState.animateTo(isChecked)
            }
        }
    }

    // 多点触控：平移、缩放、旋转
    @Composable
    fun TransformableSample() {
        // 缩放
        var scale by remember { mutableStateOf(1f) }
        // 旋转
        var rotation by remember { mutableStateOf(0f) }
        // 平移
        var offset by remember { mutableStateOf(Offset.Zero) }

        val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
            scale *= zoomChange
            rotation += rotationChange
            offset += offsetChange
        }

        Box(
            modifier = Modifier
                .graphicsLayer(
                    scaleX = scale,
                    scaleY = scale,
                    rotationZ = rotation,
                    translationX = offset.x,
                    translationY = offset.y,
                )
                .transformable(state)
                .background(Color.Blue)
                .size(100.dp, 200.dp)
        ) {

        }
    }

}

